import serial

class Arduino(object):
    """Class used for setting up communication with the Arduino Mega2560 R3"""

    __OUTPUT_PINS = -1

    def __init__(self, port, baudrate=115200):
        """this function initializes the baudrate which is how fast data is clocked
           out of the pins (the frequency)"""

        self.serial = serial.Serial(port, baudrate)

    def __str__(self):
        """this function reports the status of the Arduino: what port it is at and at
           what baud rate"""

        return "Arduino is on port %s at %d baudrate" %(self.serial.port, self.serial.baudrate)

    def output(self, pinArray):
        """this function configures the given pins in pinArray to be outputs"""

        self.__sendData(len(pinArray))

        if(isinstance(pinArray, list) or isinstance(pinArray, tuple)):
            self.__OUTPUT_PINS = pinArray
            for each_pin in pinArray:
                self.__sendData(each_pin)
        return True

    def analogWrite(self, pin, value):
        """this function writes a value to a pin"""
        
        self.__sendData('3') #3 represents a write operation as programmed into the Arduino itself
        self.__sendData(pin) #write the pin you want to access
        self.__sendData(value) #write the value that you want to write to the pin
        return True

    def analogRead(self, pin):
        """NOTE: This function is not used in the scope of our project but can be used
           later on to read information back from the Arduino"""

        self.__sendData('4') #4 represents a read operation as programmed into the Arduino
        self.__sendData(pin) #write the pin number you are trying to read from
        return self.__getData() #read from that pin

    def turnOff(self):
        """this function turns off each output pin by setting it low"""

        for each_pin in self.__OUTPUT_PINS:
            self.setLow(each_pin)
        return True

    def __sendData(self, serial_data):
        """this function actually sends data to the Arduino by using the write function"""

        while(self.__getData()[0] != "w"):
            pass
        self.serial.write(str(serial_data))

    def __getData(self):
        """this function reads information from the Arduino by using the readLine funtion"""
        return self.serial.readline().rstrip('\n')
    
    def __formatPinState(self, pinValue):
        if pinValue == '1':
            return True
        else:
            return False

    def close(self):
        """close the serial connection with the Arduino microcontroller"""

        self.serial.close()
        return True

